package com.pig4cloud.pigx.common.customize.redis.utils;

import com.pig4cloud.pigx.common.customize.redis.constants.CommonRedisConstants;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * Redis工具类
 *
 * @since 2022/8/16 10:51
 */
@Component
@AllArgsConstructor
public class RedisUtils {

    private final RedisTemplate redis;
    private final RedissonClient redisson;

    /**
     * 争夺分布式锁
     *
     * @param key    锁名
     * @param expire 过期时间，不指定时为redisson默认的30秒
     * @return {@link RLock} 返回值表示成功获取到锁，返回null表示未能获取到锁
     * @since 2022/8/16 10:54
     */
    public RLock getLock(String key, Long expire) {
        String lockKey = getLockKey(key);

        RLock lock = redisson.getLock(lockKey);
        if (Objects.isNull(expire)) {
            return lock.tryLock() ? lock : null;

        } else {
            try {
                return lock.tryLock(0L, expire, TimeUnit.MILLISECONDS) ? lock : null;
            } catch (InterruptedException e) {
            }
        }

        return null;
    }

    /**
     * 争夺分布式锁
     *
     * @param key    锁名
     * @param expire 过期时间，不指定时为redisson默认的30秒
     * @return {@link RLock}
     * @since 2022/8/16 10:54
     */
    public RLock waitLock(String key, Long expire) {
        String lockKey = getLockKey(key);

        RLock lock = redisson.getLock(lockKey);
        if (Objects.isNull(expire)) {
            lock.lock();
        } else {
            lock.lock(expire, TimeUnit.MILLISECONDS);
        }

        return lock;
    }

    /**
     * 释放占用的分布式锁
     *
     * @param lock 锁名
     * @since 2022/8/16 10:58
     */
    public void releaseLock(RLock lock) {
        if (lock.isLocked()) {
            lock.unlock();
        }
    }

    /**
     * 获得锁key
     *
     * @param key key
     * @return {@link String}
     * @since 2022/8/27 18:38
     */
    public static String getLockKey(String key) {
        return CommonRedisConstants.LOCK_POOL + ":" + key;
    }

    /**
     * 如果没有设置过期时间，设置过期时间
     *
     * @param key      key
     * @param timeout  时间数量
     * @param timeUnit 时间单位
     * @since 2022/11/11 16:20
     */
    public void setExpireIfNotSet(String key, long timeout, TimeUnit timeUnit) {
        Long expire = redis.getExpire(key);
        if (Objects.isNull(expire) || expire == -1) {
            redis.expire(key, timeout, timeUnit);
        }
    }
}
